Я перенес свой проект из Netbeans в IntelliJ Idea , пока почти все работало отлично, однако у меня были проблемы с отображением моих сущностей, как в Netbeans. Я изменил скрипт в groovy, и у меня получилось почти все, кроме случаев, когда я пытался получить отношение JPA @OneToMany , эта связь очень важна в соответствии с моделью моей базы данных.
Мой отличный сценарий
import com.intellij.database.model.DasConstraint
import com.intellij.database.model.DasTable
import com.intellij.database.model.DasObject
import com.intellij.database.model.DasDataSource
import com.intellij.database.model.ObjectKind
import com.intellij.database.util.Case
import com.intellij.database.util.DasUtil
import com.intellij.database.psi.DbColumn
import com.intellij.database.psi.DbColumnImpl
import com.intellij.database.psi.DbForeignKeyImpl
//@Grab('com.oracle:ojdbc6:11g')
//@GrabConfig(systemClassLoader=true)
import groovy.sql.Sql
//import java.sql.*
//import oracle.jdbc.driver.*
packageName = "co.com.project..."
author = "enginner"
forceNullable = (~/^(?:createdAt|created_at|updatedAt|updated_at)$/)
typeMapping = [
(~/(?i)int|number|numeric/) : "BigDecimal",
(~/(?i)float|double|decimal|real/): "double",
(~/(?i)datetime|timestamp/) : "java.sql.Timestamp",
(~/(?i)date/) : "Date",
(~/(?i)time/) : "java.sql.Time",
(~/(?i)varchar|varchar2|clob/) : "String",
(~/(?i)/) : "String"
]
FILES.chooseDirectoryAndSave("Choose directory", "Choose where to store generated files") { dir ->
SELECTION.filter { it instanceof DasTable && it.getKind() == ObjectKind.TABLE }.each { generate(it, dir) }
//SELECTION.filter { it instanceof DasDataSource }.each { generateListChild(it, dir) }
}
/*def generateListChild(datasource, dir){
def info = datasource
new File(dir, "test.java").withPrintWriter { out -> generateListChildExtend(out, info) }
}
def generateListChildExtend(out, datasource){
out.println "hello world"
out.println "datasource $datasource"
}*/
def generate(table, dir) {
def className = javaName(table.getName(), true)
def fields = calcFields(table)
new File(dir, className + ".java").withPrintWriter { out -> generate(out, className, fields, table) }
}
def connectDatabase(){
def url = 'jdbc:oracle:thin:localhost:1521:database'
def user = 'myUser'
def password = 'password'
def driver = 'oracle.jdbc.driver.OracleDriver'
def sql = Sql.newInstance(url, user, password, driver)
sql.close()
//execute statement...
}
def generate(out, className, fields, table) {
//This doesn't worked
connectDatabase()
def tableName = table.getName();
out.println "package $packageName"
out.println ""
out.println "import java.io.Serializable;"
out.println "import java.math.BigDecimal;"
out.println "import java.util.Date;"
out.println "import java.util.List;"
out.println "import javax.persistence.*;"
out.println "import javax.validation.constraints.*;"
out.println ""
out.println "/**"
out.println "*"
out.println "* @author ${author}"
out.println "*/"
out.println "@Entity"
out.println "@Table(name=\"${tableName}\")"
out.println "public class ${underscoreToCamelCase(className)} implements Serializable {"
out.println ""
out.println " private static final long serialVersionUID = 1L;"
out.println ""
def primaryKeyField
fields.each() {
if (it.annos != "") out.println " ${it.annos}"
if (it.primary) {
primaryKeyField = underscoreToCamelCase(it.name)
out.println " @Id"
out.println " @Basic(optional = false)"
out.println " @GeneratedValue(generator = \"SQ_${tableName}\")"
out.println " @SequenceGenerator(name = \"SQ_${tableName}\", sequenceName = \"SQ_${tableName}\")"
}
if (it.nullable && !it.foreign) out.println " @NotNull"
if (it.foreign) {
out.println " @JoinColumn(name = \"${it.colName}\", referencedColumnName = \"${it.colName}\")"
out.println " @ManyToOne(fetch = FetchType.LAZY)"
it.foreignKeys.each() { fk ->
if (DasUtil.containsName(it.colName, fk.getColumnsRef())) {
out.println " private ${underscoreToCamelCase(javaName(fk.getRefTableName(), true))} ${underscoreToCamelCase(it.name)};"
}
}
} else {
out.println " @Column(name=\"${it.colName}\")"
if (it.type.equals("String")) out.println " @Size(max = ${it.size})"
if (it.type.equals("Date")) out.println " @Temporal(TemporalType.TIMESTAMP)"
out.println " private ${it.type} ${underscoreToCamelCase(it.name)};"
}
out.println ""
}
fields.each() {
out.println ""
if (it.foreign) {
it.foreignKeys.each() { fk ->
if (DasUtil.containsName(it.colName, fk.getColumnsRef())) {
out.println " private ${underscoreToCamelCase(javaName(fk.getRefTableName(), true))} get${it.name.capitalize()}() {"
out.println " return ${it.name};"
out.println " }"
out.println ""
out.println " public void set${it.name.capitalize()}(${underscoreToCamelCase(javaName(fk.getRefTableName(), true))} ${it.name}) {"
out.println " this.${it.name} = ${it.name};"
out.println " }"
}
}
} else {
out.println " public ${it.type} get${it.name.capitalize()}() {"
out.println " return ${it.name};"
out.println " }"
out.println ""
out.println " public void set${it.name.capitalize()}(${it.type} ${it.name}) {"
out.println " this.${it.name} = ${it.name};"
out.println " }"
}
}
out.println ""
out.println " @Override"
out.println " public String toString() {"
out.println " return \"${packageName}.className[${primaryKeyField}=\" + ${primaryKeyField} + \"];\""
out.println " }"
out.println ""
out.println "}"
}
def calcFields(table) {
DasUtil.getColumns(table).reduce([]) { fields, col ->
def spec = Case.LOWER.apply(col.getDataType().getSpecification())
def typeStr = typeMapping.find { p, t -> p.matcher(spec).find() }.value
def colName = (String) col.getName()
def size = col.getDataType().getLength()
def nullable = col.isNotNull()
def foreign = DasUtil.isForeign(col)
def foreignKeys = DasUtil.getForeignKeys(table)
fields += [[
name : javaName(col.getName(), false),
type : typeStr,
annos : "",
colName : col.getName(),
size : size,
primary : DasUtil.isPrimary(col),
nullable : nullable,
foreign : foreign,
foreignKeys: foreignKeys
]]
}
}
def javaName(str, capitalize) {
def s = com.intellij.psi.codeStyle.NameUtil.splitNameIntoWords(str)
.collect { Case.LOWER.apply(it).capitalize() }
.join("")
.replaceAll(/[^\p{javaJavaIdentifierPart}[_]]/, "_")
capitalize || s.length() == 1 ? s : Case.LOWER.apply(s[0]) + s[1..-1]
}
String underscoreToCamelCase(String underscore) {
if (!underscore || underscore.isAllWhitespace()) {
return ''
}
return underscore.replaceAll(/_\w/) { it[1].toUpperCase() }
}
После нескольких тестов (и неудачных) с различными методами класса ( com.intellij.database.util.DasUtil ) я решил попробовать выполнитьследующий запрос, который возвращает все таблицы в отношении @OneToMany таблицы в генерации.
SELECT tableChilds.*,
(CASE WHEN rowRepeat > 1 THEN tableName||'_LIST'||rowRepeat ELSE tableName||'_LIST' END) AS childList
FROM (SELECT b.table_name tableName,
b.column_name columnName,
row_number() over (partition by b.table_name order by 1) rowRepeat
FROM all_cons_columns b,
all_cons_columns c,
all_constraints a
WHERE b.constraint_name = a.constraint_name
AND a.owner = b.owner
AND b.position = c.position
AND c.constraint_name = a.r_constraint_name
AND c.owner = a.r_owner
AND a.constraint_type = 'R'
AND a.owner = 'OWNER'
AND c.table_name = 'MY_TABLE'
ORDER BY 1
) tableChilds;
Однако мне не удалось повторно использовать соединение источника данных с базой данных из этого сценария, а также при созданииновое соединение, чтобы запустить этот запрос и решить мою проблему. Итак, возможно ли, что с помощью классов, предоставляемых IntelliJ для отображения этого типа ассоциации? Или как я могу создать новое соединение с БД из этого сценария, учитывая, что я уже использую аннотацию @Grab для импорта драйвераJDBC?
Ненавижу снова открывать Netbeans просто для отображения моих сущностей, есть идеи для решения этой проблемы? я использую последнюю версию для интеллигентной идеи (2019.2.2).