I am recently working on a task where I am refactoring an old web project. First I tried to run the project on my local weblogic instance before starting refactoring.
While I try to deploy the application I got a hibernate exception as follows ==>
Caused By: org.hibernate.AnnotationException: Unknown Id.generator: unique-id
at org.hibernate.cfg.BinderHelper.makeIdGenerator(BinderHelper.java:428)
at org.hibernate.cfg.AnnotationBinder.bindId(AnnotationBinder.java:1901)
at org.hibernate.cfg.AnnotationBinder.processElementAnnotations(AnnotationBinder.java:1279)
at org.hibernate.cfg.AnnotationBinder.bindClass(AnnotationBinder.java:754)
at org.hibernate.cfg.AnnotationConfiguration.processArtifactsOfType(AnnotationConfiguration.java:546)
Truncated. see log file for complete stacktrace
The exception above implying that it couldn't find the id generator named "unique-id" . Then I dig in to the code and see that the id field in the entity is string. and there is a custom ID generator class that is implementing hibernate IdentifierGenerator class where it is calling a db function for generating alphanumeric id for each time it is called. Below is piece of code in the entity class where it defines the type of id generation.
#Id
#Column(name = "ID", nullable = false, length = 18)
#GenericGenerator(name = "unique-id", strategy = "com.common.entity.RowIdGenerator")
#GeneratedValue(strategy = GenerationType.IDENTITY, generator = "unique-id")
private String id;
And here is the RowIdGenerator class for generating alphanumeric id.
public class RowIdGenerator implements IdentifierGenerator
{
private final static String SQL_TEXT = "SELECT TCC.F_ROW_ID_GEN FROM DUAL";
#Override
public Serializable generate(SessionImplementor sessionImplemetor, Object object) throws HibernateException
{
return this.getNextNumber(sessionImplemetor);
}
private String getNextNumber(SessionImplementor session)
{
try
{
ResultSet rs = null;
PreparedStatement statement = null;
try
{
statement = session.getBatcher().prepareSelectStatement(SQL_TEXT);
rs = statement.executeQuery();
String nextValue = null;
if (rs.next())
nextValue = rs.getString(1);
if (nextValue == null)
throw new HibernateException("is is null.");
return nextValue;
}
finally
{
if (rs != null)
rs.close();
if (statement != null)
session.getBatcher().closeStatement(statement);
}
} catch (SQLException sqle)
{
throw JDBCExceptionHelper.convert(session.getFactory().getSQLExceptionConverter(), sqle, "could not fetch initial value for increment generator", SQL_TEXT);
}
}
}
What may cause this error? I see that the generator named "unique-id" is defined and annotated. As far as I know there is no error in the code, maybe it is because of the configuration of my local weblogic instance but Any comment and advice would be appreciated.
regards
You can auto generate only number as ids.Auto generation for other types like String is not supported by hibernate
Related
Here , I want to hardcode some things into db at the action of server starts with Spring commandline runner
Problem :- In this I have checked that if 1L isn't present then do entry for that with Id 1L but still it stores to incremental Id when 1L or 2L or 3L is not present there.
My Entity In which I'm doing entry :-
Product Type
#Data
#Entity
#Table(name = "tbl_product_type_chemical")
public class ProductType implements IBaseData<Long> {
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Id
private Long id;
private String name;
#Column(columnDefinition = "text")
private String description;
}
This is method of Runner :-
private void loadProductTypeNew() throws Exception {
String SUBMODULE = " [Init Data] " + " [loadProductTypeNew()] ";
try {
ProductType fp = productTypeRepository.getOne(1L);
if (null == fp) {
fp = new ProductType();
fp.setId(1L);
fp.setName("FINISH PRODUCT");
productTypeRepository.save(fp);
}
ProductType rm = productTypeRepository.getOne(2L);
if (null != rm) {
rm = new ProductType();
rm.setId(2L);
rm.setName("RAW MATERIAL");
productTypeRepository.save(rm);
}
ProductType sm = productTypeRepository.getOne(3L);
if (null != sm) {
sm = new ProductType();
sm.setId(3L);
sm.setName("SUPPORTING MATERIAL");
productTypeRepository.save(sm);
}
} catch (Exception ex) {
ApplicationLogger.logger.error(SUBMODULE + ex.getMessage(), ex);
throw ex;
}
}
#Override
public void run(String... args) throws Exception {
loadProductTypeNew();`
}
Output :-
9 SUPPORTING MATERIAL
8 RAW MATERIAL
7 FINISH PRODUCT
10 FINISH PRODUCT
11 RAW MATERIAL
12 SUPPORTING MATERIAL
13 RAW MATERIAL
14 SUPPORTING MATERIAL
And I am calling it in run method.If anyone can solve thanks in advance
Nothing in your application should depend on specific values of the id field since it is generated by the database.
I suggest therefore to identify a business key (in your case the name), ensure it is unique with a primary key and use that to determine if a a row needs to be inserted in the database.
Your code would look similar to this
if (productTypeRepository.existsByName(""FINISH PRODUCT")) {
ProductType fp = new ProductType();
fp.setName("FINISH PRODUCT");
productTypeRepository.save(fp);
}
I am having trouble getting data from a database I know exists and I know the format of.
In the code snippet below the "if conn != null" is just a test to verify the database name, table name, etc are all correct, and they DO verify.
The last line below is what generates the exception
public static HashMap<Integer, String> getNetworkMapFromRemote(DSLContext dslRemote, Connection conn, Logger logger) {
HashMap<Integer,String> remoteMap = new HashMap<Integer, String>();
// conn is only used for test purposes
if (conn != null) {
// test to be sure database is ok
try
{
ResultSet rs = conn.createStatement().executeQuery("SELECT networkid, name FROM network");
while (rs.next()) {
System.out.println("TEST: nwid " + rs.getString(1) + " name " + rs.getString(2));
}
rs.close();
}
catch ( SQLException se )
{
logger.trace("getNetworksForDevices SqlException: " + se.toString());
}
}
// ----------- JOOQ problem section ------------------------
Network nR = Network.NETWORK.as("network");
// THE FOLLOWING LINE GENERATES THE UNKNOWN TABLE
Result<Record2<Integer, String>> result = dslRemote.select( nR.NETWORKID, nR.NAME ).fetch();
This is the output
TEST: nwid 1 name Network 1
org.jooq.exception.DataAccessException: SQL [select `network`.`NetworkId`, `network`.`Name` from dual]; Unknown table 'network' in field list
at org.jooq.impl.Utils.translate(Utils.java:1288)
at org.jooq.impl.DefaultExecuteContext.sqlException(DefaultExecuteContext.java:495)
at org.jooq.impl.AbstractQuery.execute(AbstractQuery.java:327)
at org.jooq.impl.AbstractResultQuery.fetch(AbstractResultQuery.java:330)
at org.jooq.impl.SelectImpl.fetch(SelectImpl.java:2256)
at com.nvi.kpiserver.remote.KpiCollectorUtil.getNetworkMapFromRemote(KpiCollectorUtil.java:328)
at com.nvi.kpiserver.remote.KpiCollectorUtilTest.testUpdateKpiNetworksForRemoteIntravue(KpiCollectorUtilTest.java:61)
.................
Caused by: com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: Unknown table 'network' in field list
.................
For the sake of completness here is part of the JOOQ generated class file for Network
package com.wbcnvi.intravue.generated.tables;
#javax.annotation.Generated(value = { "http://www.jooq.org", "3.3.1" },
comments = "This class is generated by jOOQ")
#java.lang.SuppressWarnings({ "all", "unchecked", "rawtypes" })
public class Network extends org.jooq.impl.TableImpl<com.wbcnvi.intravue.generated.tables.records.NetworkRecord> {
private static final long serialVersionUID = 1729023198;
public static final com.wbcnvi.intravue.generated.tables.Network NETWORK = new com.wbcnvi.intravue.generated.tables.Network();
#Override
public java.lang.Class<com.wbcnvi.intravue.generated.tables.records.NetworkRecord> getRecordType() {
return com.wbcnvi.intravue.generated.tables.records.NetworkRecord.class;
}
public final org.jooq.TableField<com.wbcnvi.intravue.generated.tables.records.NetworkRecord, java.lang.Integer> NWID = createField("NwId", org.jooq.impl.SQLDataType.INTEGER.nullable(false), this, "");
public final org.jooq.TableField<com.wbcnvi.intravue.generated.tables.records.NetworkRecord, java.lang.Integer> NETWORKID = createField("NetworkId", org.jooq.impl.SQLDataType.INTEGER.nullable(false).defaulted(true), this, "");
public final org.jooq.TableField<com.wbcnvi.intravue.generated.tables.records.NetworkRecord, java.lang.String> NAME = createField("Name", org.jooq.impl.SQLDataType.CHAR.length(40).nullable(false).defaulted(true), this, "");
public final org.jooq.TableField<com.wbcnvi.intravue.generated.tables.records.NetworkRecord, java.lang.Integer> USECOUNT = createField("UseCount", org.jooq.impl.SQLDataType.INTEGER.nullable(false).defaulted(true), this, "");
public final org.jooq.TableField<com.wbcnvi.intravue.generated.tables.records.NetworkRecord, java.lang.Integer> NETGROUP = createField("NetGroup", org.jooq.impl.SQLDataType.INTEGER.nullable(false).defaulted(true), this, "");
public final org.jooq.TableField<com.wbcnvi.intravue.generated.tables.records.NetworkRecord, java.lang.String> AGENT = createField("Agent", org.jooq.impl.SQLDataType.CHAR.length(16), this, "");
public Network() {
this("network", null);
}
public Network(java.lang.String alias) {
this(alias, com.wbcnvi.intravue.generated.tables.Network.NETWORK);
}
..........
Based on the "unknown table" exception I thought there was a problem connected to the wrong database or wrong server, but the console output is correct for a JDBC query.
Any thoughts are appreciated, perhaps something else can be the root cause or the DSLContext is not valid (but I would think that would generate a different exception).
The answer ends up being simple, I did not include the .from() method
Result<Record2<Integer, String>> result = dslRemote.select( nR.NETWORKID, nR.NAME )
.from(nR)
.fetch();
That is why the table was unknown, I never put the from method in.
I am using JDO in GAE. I have two JDO classes having one to many relationship. parent class is
#PersistenceCapable(detachable="true")
#FetchGroup(name="childerns", members={#Persistent(name="aliasName")})
public class IdentityProvider {
#PrimaryKey
#Persistent
private String url;
#Persistent
private String domainName;
#Persistent
#Element(dependent = "true")
private ArrayList<AliasDomain> aliasName = new ArrayList<AliasDomain>();
}
The child classes is
#PersistenceCapable(detachable = "true")
public class AliasDomain {
#Persistent
private String url;
#Persistent
private String aliasName;
#PrimaryKey
#Persistent(valueStrategy = IdGeneratorStrategy.IDENTITY)
private Key key;
}
I am just performing CURD operations on both entity. First i create the parent instance and then i create the child instance as
public void addAliasDomain(AliasDomain domain) {
String url = domain.getUrl();
PersistenceManager pm = PMFSingleton.get().getPersistenceManager();
IdentityProvider idp = null;
Transaction txn = null;
try {
txn = pm.currentTransaction();
txn.begin();
pm.getFetchPlan().addGroup("childerns");
idp = pm.getObjectById(IdentityProvider.class, url);
idp = pm.detachCopy(idp);
idp.getAliasName().add(domain);
pm.makePersistent(idp);
txn.commit();
} catch (Exception e) {
e.printStackTrace();
} finally {
if ( txn.isActive() ) {
txn.rollback();
}
pm.close();
}
}
My issue is created when i delete any child instance. As you see from the above function i link the child to the parents( means add child object into arrayList). So when child is deleted its reference in the parents is not deleted so at the detached time of parents object i got exception which is as
Object of type "user.oauth.jdo.model.IdentityProvider" and identity "yahoo.com" was not detached correctly. Please consult the log for any possible information.
org.datanucleus.exceptions.NucleusUserException: Object of type "user.oauth.jdo.model.IdentityProvider" and identity "yahoo.com" was not detached correctly. Please consult the log for any possible information.
at org.datanucleus.state.JDOStateManager.detachCopy(JDOStateManager.java:2942)
at org.datanucleus.ObjectManagerImpl.detachObjectCopy(ObjectManagerImpl.java:2591)
at org.datanucleus.api.jdo.JDOPersistenceManager.jdoDetachCopy(JDOPersistenceManager.java:1145 )
at org.datanucleus.api.jdo.JDOPersistenceManager.detachCopy(JDOPersistenceManager.java:1174)
at user.oauth.data.broker.IDPJDOBroker.retrieveDomainList(IDPJDOBroker.java:49)
The code of function retreiveDomainList in IDPJDOBroker is
public List retrieveDomainList() {
PersistenceManager pm = PMFSingleton.get().getPersistenceManager();
Query query = pm.newQuery(IdentityProvider.class);
List<IdentityProvider> list = null;
List<IdentityProvider> detachedList = null;
IdentityProvider idp = null;
try {
pm.getFetchPlan().addGroup("childerns");
list = (List<IdentityProvider>) query.execute();
detachedList = new ArrayList<IdentityProvider>();
for(IdentityProvider obj : list){
idp = pm.detachCopy(obj);
OAuthJDOBroker broker = new OAuthJDOBroker();
int actUsers = 0;
if ( idp.getHistory() != null && idp.getHistory().size() > 0) {
actUsers = broker.calculateActiveUser(idp.getUserActiveDuration(),idp.getDomainName());
}
idp.setActiveUsers(actUsers);
detachedList.add(idp);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
query.closeAll();
pm.close();
}
return detachedList;
}
Please tell me what to do? Is it not possible in JDO to delete the child? if it is possible then how to do it properly.
I have just seen this, but in case anyone arrives here, to delete a child object in a one to many relationship you must delete the reference from the parent, the child object will be deleted "transparently"
I have a problem using GAEJ and JDO for storing the data.
This is what I'm working with:
class Usuari.java:
#PrimaryKey
#Persistent(valueStrategy = IdGeneratorStrategy.IDENTITY)
private Key key;
#Persistent
private String email;
#Persistent
private String rol="";
class DBUtils.java:
I've tried with two ways of doing the delete operation:
// This method removes a record from the database using its unique Key
public static boolean eliminar(Key k) throws Exception {
PersistenceManager pm = PMF.get().getPersistenceManager();
String kind;
Long id;
kind = k.getKind();
id = k.getId();
try {
if (k.getKind().equals("Usuari")) {
Usuari u = (Usuari)pm.getObjectById(k);
pm.deletePersistent(u);
_log.log(Level.INFO, "Deleted an entity->kind: " + kind + " id: " + id);
}
return true;
} catch (Exception e) {
_log.log(Level.SEVERE, "Unable to delete an entity->kind: " + kind + " id: " + id);
System.err.println(e.getMessage());
throw e;
}
finally {
pm.close();
}
}
// This method removes a record from the database using its unique Key - too
public static void eliminar2(Key k) throws Exception {
PersistenceManager pm = PMF.get().getPersistenceManager();
javax.jdo.Transaction tx = pm.currentTransaction();
try
{
tx.begin();
if (k.getKind().equals("Usuari")) {
Usuari u = (Usuari) pm.getObjectById(k);
pm.deletePersistent(u);
}
tx.commit();
}
catch (Exception e)
{
if (tx.isActive())
{
tx.rollback();
}
throw e;
}
}
I'm able to create new instances of some class "Usuari" but I can't delete them.
Everytime I call "eliminar" or "eliminar2" methods I get a "No such object" as result of trying to fetch it. I've checked manually and I see the object exists in my admin panel, with its ID and KIND, so I don't know what am I doing wrong.
Any help would be much appreciated.
PM.getObjectById does not take in a Key object, as per the JDO spec. It takes in an identity object, the same type as you would get from pm.getObjectId(obj); suggest you glance through the JDO spec. No doubt if you inspected what is returned from this method you would see that it can't find an object with that 'identity' because a Key is not an identity. You can also do
pm.getObjectById(Usuari.class, key);
which is shown very clearly in GAE documentation.
Still don't get why users are putting #Persistent on every field virtually every type is default persistent; only leads to making code more unreadable.
had several apps with jdbc and Oracle 10g. Now I´m changing the apps for use c3p0. But I have some problems working with Oracle types.
I Have this Oracle type:
CREATE OR REPLACE
TYPE DATAOBJ AS OBJECT
(
ID NUMBER,
NAME VARCHAR2(50)
)
And this Oracle function:
CREATE OR REPLACE FUNCTION F_IS_DATA_OBJECT (datar in DATAOBJ) RETURN varchar2 IS
tmpVar varchar2(150);
BEGIN
tmpVar := 'Data object:';
if datar.id is not null then
tmpVar := tmpVar || 'id=' || datar.ID;
end if;
if datar.name is not null then
tmpVar := tmpVar || 'name=' || datar.name;
end if;
return tmpVar;
EXCEPTION
WHEN NO_DATA_FOUND THEN
NULL;
WHEN OTHERS THEN
RAISE;
END F_IS_DATA_OBJECT;
then I have a app in Java with c3p0 with next classes:
Dataobj.class to represent the object type:
package c3p0pruebas.modelo;
import java.io.Serializable;
import java.sql.SQLData;
import java.sql.SQLException;
import java.sql.SQLInput;
import java.sql.SQLOutput;
public class Dataobj implements SQLData, Serializable {
private String name;
private Integer id;
public Dataobj() {
}
public String getSQLTypeName() {
return "DATAOBJ";
}
public void writeSQL(SQLOutput stream) throws SQLException {
stream.writeInt(id.intValue());
stream.writeString(name);
}
public void readSQL(SQLInput stream, String typeName) throws SQLException {
id = new Integer(stream.readInt());
name = stream.readString();
}
public void setName(String name) {
this.name = name;
}
public String getName() {
return name;
}
... and its gets and sets ....
And the main class and main method:
Connection connection = DBConnectionManager.getInstance().getConnection("Mypool"); //I use a class to get connection
CallableStatement cs = null;
String error = "";
try {
/*
//First I made a NativeExtractor of the connection, but the result is the same, I got it from Spring framework.
//C3P0NativeJdbcExtractor extractor = new C3P0NativeJdbcExtractor();
//OracleConnection newConnection = (OracleConnection) extractor.getNativeConnection(connection);
//cs = (OracleCallableStatement) newConnection.prepareCall("{? = call F_IS_DATA_OBJECT(?)}");
*/
//Creates the object
Dataobj obj = new Dataobj();
obj.setId(new Integer(33));
obj.setName("myName");
cs = connection.prepareCall("{? = call F_IS_DATA_OBJECT(?)}");
cs.registerOutParameter(1, OracleTypes.VARCHAR);
cs.setObject(2, obj);
cs.execute();
error = cs.getString(1);
System.out.println("Result: " + error);
} catch (SQLException e) {
e.printStackTrace();
} catch (Exception ex) {
ex.printStackTrace();
} finally {
closeDBObjects(null,cs,null);
}
closeDBObjects(null, null, connection); //Close connection
The execution gets:
Data object: id=33.
I cant get the String (Varchar2) value, the name string.
With oracle arrays of object type, I have the same problem, It worked nice with JDBC. When I worked with Arrays, also, it hasn´t the string values:
//Here I use a NativeConnection ...
Dataobj arrayOfData[] = new Dataobj[myDataObj.size()];
... //Makes the array of DataObj.
ArrayDescriptor descriptor = ArrayDescriptor.createDescriptor("OBJ_ARRAY", newConnection);
ARRAY arrayDatas = new ARRAY(descriptor, newConnection, arrayOfData);
//In this step, objects of arrayDatas haven´t the name string...
Thanks!!!
OK, It finally works.
Searching, We found out the answer:
We change data definition in the database and now it works:
CREATE OR REPLACE
TYPE "DATAOBJ" AS OBJECT
(
vid NUMBER,
vname NCHAR(50)
)
Thanks!
I had the same problem and i solved without change VARCHAR2 to NCHAR, because for me, the NCHAR doesn't appear the String in the Oracle, stay "?" in all the positions.
I changed the oracle driver of the WAR to the version of my database, in my case was 11.2.0.1.0:
http://www.oracle.com/technetwork/database/enterprise-edition/jdbc-112010-090769.html
And i put another driver, that is the NLS for Oracle Objects and Collections:
http://download.oracle.com/otn/utilities_drivers/jdbc/112/orai18n.jar
With this, i solved the problem and the VARCHAR2 worked fine.
Good luck.